#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/framework/LocalFileFormatTarget.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>

#ifndef DOM_HPP
#define DOM_HPP
#include <xercesc/dom/DOM.hpp>
#endif

#include "boinc_api.h"
#include "util.h"
#include "filesys.h"

#include "lip.h"

#include "ddas_globals.h"
#include "ddas_client_io.h"
#include "ddas_debug.h"
#include "ddas_client_setup.h"

XERCES_CPP_NAMESPACE_USE
using namespace std;


/**
* @author Max Rupplin
* @date 5-15-08
* 
* 'ddas_delete_state_file' is an utility function to delete the state file. This method isn't actually called anywhere.
*/
int ddas_delete_state_file()
{
	string resolved_name;

	int retval = boinc_resolve_filename_s(STATE_FILE, resolved_name);
	if (retval)
	{
		cerr<<"Couldn't resolve STATE_FILE's name, \""<<STATE_FILE<<"\"."<<endl;
	}

	return remove( resolved_name.c_str() );
}


/**
* @author Max Rupplin 
* @date 5-3-08
* @param coeff_matrix The coefficient matrix. It holds the indices and their respective values for a given regression iteration.
* @param iteration The current iteration.
* @param vector The vector holding the coefficient values
*
* 'generate_coefficient_matrix' matches coefficient indices w/ values and stores them in a gsl_matrix.
*/
void generate_coefficient_matrix( gsl_matrix* coeff_matrix, verylong iteration, gsl_vector* vector )
{
	//big-endian (left-most bit is most significant)
	char* binary_representation = ddas_verylong_to_binary_char(iteration);

	//in which index are we interested
	int vector_index = 0;

	for(int i=0; i<independent_var_count; i++)
	{		
		//the index is the iteration
		gsl_matrix_set( coeff_matrix, 0, i , i );

		//based on binary char decide what to do
		if(binary_representation[i] == '1') 
		{
			//coefficient value = gsl_vector_get(vector, vector_index)
			gsl_matrix_set( coeff_matrix, 1 , i , gsl_vector_get(vector, vector_index) );

			//get next value next time
			vector_index++;
		}
		else if(binary_representation[i] == '0') 
		{
			//coefficient value = 0
			gsl_matrix_set( coeff_matrix, 1, i , 0 );
		}
	}

	//free memory
	delete[] binary_representation;
}

/**
* @author Max Rupplin
* @date 5-15-08
* @param file The file pointer.
*
* 'get file size' returns the size, in bytes, of a file. 
*/
long get_file_size( FILE* file )
{
	//code sourced from: http://www.cplusplus.com/doc/tutorial/files.html

	long begin,end;
  
	ifstream myfile (file);
	begin = myfile.tellg();
	myfile.seekg (0, ios::end);
	end = myfile.tellg();
	myfile.close();

	return (end-begin);
}

/**
* @author Max Rupplin
* @date 5-15-08
* @param iteration The current regression iteration.
*
* 'write the state file' takes the current iteration and the globally scoped DDAS_CLIENT_RESULT_SET 'result_set'
* and writes to disk the best 'num_results' regressions to disk in a file called 'state'. 'state' is a logical name
* by which BOINC refers to the actual file name.
*/
int ddas_write_state_to_file(verylong iteration)
{
	DOMAttr*			iteration_attr;
	DOMAttr*			bin_rep;
	DOMAttr*			definition_number;
	DOMAttr*			SSE;
	DOMDocument*		doc;
	DOMElement*			root;
	DOMElement*			data_row;
	DOMImplementation*	impl;	

	XMLCh* LS;	
	XMLCh* root_ch;
	XMLCh* data_row_ch;
	XMLCh* def_num_ch;	
	XMLCh* SSE_ch;	
	XMLCh* coef_ch;	
	XMLCh* value_ch;
	XMLCh* id_ch;
	XMLCh* bin_rep_ch;
	XMLCh* iteration_ch;

	//requisite xerces initialization
    try
    {
		XMLPlatformUtils::Initialize(); 
	}
	catch( XMLException& e )
	{
		char* message = XMLString::transcode( e.getMessage() );
		cerr << "XML toolkit initialization error: " << message << endl;
		XMLString::release( &message );

		#ifdef DEBUG_MODE
		cerr<<"ddas_write_results_to_file returning "<<SERIALIZATION_FAILURE<<"."<<endl;
		#endif

		return SERIALIZATION_FAILURE;
	}

	//create DOM document for subsequent serialization
	try
	{
		//vars
		LS			= XMLString::transcode("LS");	
		root_ch		= XMLString::transcode("DDAS_result_set");
		data_row_ch	= XMLString::transcode("data_row");
		def_num_ch	= XMLString::transcode("definition_number");
		SSE_ch		= XMLString::transcode("SSE");
		coef_ch		= XMLString::transcode("regression_coefficient");
		value_ch	= XMLString::transcode("value");
		id_ch		= XMLString::transcode("id");
		bin_rep_ch	= XMLString::transcode("binary");
		iteration_ch= XMLString::transcode("iteration"); 

		//initialize DOM and DOMDocument
		impl	= DOMImplementationRegistry::getDOMImplementation(LS);
		doc		= impl->createDocument(0, root_ch, 0);
		root	= doc->getDocumentElement();

		char buffer[128];
		zswrite(buffer, iteration);
		iteration_attr = doc->createAttribute(iteration_ch);
		iteration_attr->setValue(XMLString::transcode(buffer));
		root->setAttributeNode(iteration_attr);

		//for each result in result_set
		for(int i=0; i<results_to_return; i++)
		{
			DDAS_CLIENT_RESULT* current_result = &(result_set->result[i]);

			//create DOMNodes for current data_row
			data_row			= doc->createElement(data_row_ch);
			bin_rep				= doc->createAttribute(bin_rep_ch);	
			definition_number	= doc->createAttribute(def_num_ch);
			SSE					= doc->createAttribute(SSE_ch);

			//convert numeric representations to strings
			char def_buffer [128];
			char sse_buffer [128];
			zswrite(def_buffer, current_result->definition_number);
			sprintf (sse_buffer, "%f", current_result->sse);

			//transcode from char* to XMLCh* representation
			XMLCh* bin_rep_val	= XMLString::transcode( ddas_verylong_to_binary_char(current_result->definition_number) );
			XMLCh* def_num_val	= XMLString::transcode( def_buffer );
			XMLCh* SSE_val		= XMLString::transcode( sse_buffer );

			//set data_row's attribute's values			
			bin_rep				->setValue(bin_rep_val);
			definition_number	->setValue(def_num_val);
			SSE					->setValue(SSE_val);

			//add attributes to current data_row
			data_row->setAttributeNode(definition_number);
			data_row->setAttributeNode(SSE);			
			data_row->setAttributeNode(bin_rep);
			
			//append current data_row to root DOMElement
			root->appendChild(data_row);

			//create coefficient nodes and their values					
			DOMAttr* index_attribute;
			DOMAttr* value_attribute;			
			DOMElement* coefficient_element;

			//length of binary string
			unsigned int string_length = (unsigned int)strlen(ddas_verylong_to_binary_char(current_result->definition_number));
			
			//create a matrix to store the coefficients and their indices
			gsl_matrix* coefficient_matrix = gsl_matrix_alloc( 2, string_length );

			//populate the matrix with the coefficients and their indices
			generate_coefficient_matrix( coefficient_matrix, current_result->definition_number, current_result->regression_coefficients );
			
			//append the coefficient values w/ respective indices to XML doc
			for(unsigned int j=0; j<string_length; j++)
			{
				coefficient_element = doc->createElement(coef_ch);
				index_attribute     = doc->createAttribute(id_ch);
				value_attribute     = doc->createAttribute(value_ch);   
				
				char* index = new char[128];
				char* value = new char[128];

				sprintf ( index, "%u", j );
				sprintf ( value, "%f", gsl_matrix_get(coefficient_matrix, 1, j) );

				index_attribute->setValue( XMLString::transcode(index) );
				value_attribute->setValue( XMLString::transcode(value) );

				coefficient_element->setAttributeNode(index_attribute);
				coefficient_element->setAttributeNode(value_attribute);

                data_row->appendChild(coefficient_element);

				delete[] index;
				delete[] value;
			}

			gsl_matrix_free( coefficient_matrix );

		}//end outer for-loop		
	}
	catch( XMLException& e )
	{
		char* message = XMLString::transcode( e.getMessage() );
		cerr << "The following error occurred during the DOM creation: " << message << endl;
		XMLString::release( &message );

		#ifdef DEBUG_MODE
		cerr<<"ddas_write_results_to_file returning "<<SERIALIZATION_FAILURE<<"."<<endl;
		#endif

		return SERIALIZATION_FAILURE;
	}



	//serialize DOM document to local text file (LocalFileFormatTarget class)
	try
	{
		string resolved_name;
		int retval;

		//allocation
		DOMWriter* writer = ((DOMImplementationLS*)impl)->createDOMWriter();

		//resolve file name via BOINC's API
		retval = boinc_resolve_filename_s(STATE_FILE, resolved_name);
		if (retval)
		{
			cerr<<"Couldn't resolve STATE_FILE's name, \""<<STATE_FILE<<"\"."<<endl;
		}

		XMLCh* file=XMLString::transcode( resolved_name.c_str() );
		LocalFileFormatTarget local_file(file);
		
		//set some writer output preferences
		if (writer->canSetFeature(XMLUni::fgDOMWRTDiscardDefaultContent, true))
			writer->setFeature(XMLUni::fgDOMWRTDiscardDefaultContent, true);
		if (writer->canSetFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true))
			writer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true);	
		
		//write root node and its children
		writer->writeNode(&local_file, *root);

		//free memory
		writer->release();
		XMLString::release(&file);
	}
	catch( XMLException& e )
	{
		char* message = XMLString::transcode( e.getMessage() );
		cerr << "XML toolkit initialization error: " << message << endl;
		XMLString::release( &message );
		
		#ifdef DEBUG_MODE
		cerr<<"ddas_write_state_to_file returning "<<SERIALIZATION_FAILURE<<"."<<endl;
		#endif

		return SERIALIZATION_FAILURE;
	}



	//required xerces teardown
	try
    {
		XMLPlatformUtils::Terminate();		
	}
    catch( xercesc::XMLException& e )
    {
		char* message = XMLString::transcode( e.getMessage() );
		cerr << "XML toolkit teardown error: " << message << endl;
		XMLString::release( &message );

		#ifdef DEBUG_MODE
		cerr<<"ddas_write_state_to_file returning "<<SERIALIZATION_FAILURE<<"."<<endl;
		#endif

		return SERIALIZATION_FAILURE;
    }	

	#ifdef DEBUG_MODE
	cerr<<"ddas_write_state_to_file returning "<<SERIALIZATION_SUCCESS<<"."<<endl;
	#endif

	return SERIALIZATION_SUCCESS;
}

/**
* @author Max Rupplin
* @date 5-15-08
* @param results The globally scoped DDAS_CLIENT_RESULT_SET struct containing the best results.
*
* 'ddas_write_results_to_file' writes the final result file, called 'result' to disk
*/ 
int ddas_write_results_to_file(DDAS_CLIENT_RESULT_SET* results)
{

	DOMAttr*			bin_rep;
	DOMAttr*			definition_number;
	DOMAttr*			SSE;
	DOMDocument*		doc;
	DOMElement*			root;
	DOMElement*			data_row;
	DOMImplementation*	impl;	

	XMLCh* LS;	
	XMLCh* root_ch;
	XMLCh* data_row_ch;
	XMLCh* def_num_ch;	
	XMLCh* SSE_ch;	
	XMLCh* coef_ch;	
	XMLCh* value_ch;
	XMLCh* id_ch;
	XMLCh* bin_rep_ch;

	//requisite xerces initialization
    try
    {
		XMLPlatformUtils::Initialize(); 
	}
	catch( XMLException& e )
	{
		char* message = XMLString::transcode( e.getMessage() );
		cerr << "XML toolkit initialization error: " << message << endl;
		XMLString::release( &message );

		#ifdef DEBUG_MODE
		cerr<<"ddas_write_results_to_file returning "<<SERIALIZATION_FAILURE<<"."<<endl;
		#endif

		return SERIALIZATION_FAILURE;
	}

	//create DOM document for subsequent serialization
	try
	{
		//vars
		LS			= XMLString::transcode("LS");	
		root_ch		= XMLString::transcode("DDAS_result_set");
		data_row_ch	= XMLString::transcode("data_row");
		def_num_ch	= XMLString::transcode("definition_number");
		SSE_ch		= XMLString::transcode("SSE");
		coef_ch		= XMLString::transcode("regression_coefficient");
		value_ch	= XMLString::transcode("value");
		id_ch		= XMLString::transcode("id");
		bin_rep_ch	= XMLString::transcode("binary");

		//initialize DOM and DOMDocument
		impl	= DOMImplementationRegistry::getDOMImplementation(LS);
		doc		= impl->createDocument(0, root_ch, 0);
		root	= doc->getDocumentElement();

		//for each result in result_set
		for(int i=0; i<results_to_return; i++)
		{
			DDAS_CLIENT_RESULT* current_result = &(result_set->result[i]);

			//create DOMNodes for current data_row
			data_row			= doc->createElement(data_row_ch);
			bin_rep				= doc->createAttribute(bin_rep_ch);	
			definition_number	= doc->createAttribute(def_num_ch);
			SSE					= doc->createAttribute(SSE_ch);

			//convert numeric representations to strings
			char def_buffer [128];
			char sse_buffer [128];
			zswrite(def_buffer, current_result->definition_number);
			sprintf (sse_buffer, "%f", current_result->sse);

			//transcode from char* to XMLCh* representation
			XMLCh* bin_rep_val	= XMLString::transcode( ddas_verylong_to_binary_char(current_result->definition_number) );
			XMLCh* def_num_val	= XMLString::transcode( def_buffer );
			XMLCh* SSE_val		= XMLString::transcode( sse_buffer );

			//set data_row's attribute's values			
			bin_rep				->setValue(bin_rep_val);
			definition_number	->setValue(def_num_val);
			SSE					->setValue(SSE_val);

			//add attributes to current data_row
			data_row->setAttributeNode(definition_number);
			data_row->setAttributeNode(SSE);			
			data_row->setAttributeNode(bin_rep);
			
			//append current data_row to root DOMElement
			root->appendChild(data_row);

			//create coefficient nodes and their values					
			DOMAttr* index_attribute;
			DOMAttr* value_attribute;			
			DOMElement* coefficient_element;

			//length of binary string
			unsigned int string_length = (unsigned int)strlen(ddas_verylong_to_binary_char(current_result->definition_number));
			
			//ddas_print_client_result( current_result );

			//create a matrix to store the coefficients and their indices
			gsl_matrix* coefficient_matrix = gsl_matrix_alloc( 2, string_length );

			//populate the matrix with the coefficients and their indices
			generate_coefficient_matrix( coefficient_matrix, current_result->definition_number, current_result->regression_coefficients );

			//ddas_print_gsl_matrix( coefficient_matrix );
			
			//append the coefficient values w/ respective indices to XML doc
			for(unsigned int j=0; j<string_length; j++)
			{
				coefficient_element = doc->createElement(coef_ch);
				index_attribute     = doc->createAttribute(id_ch);
				value_attribute     = doc->createAttribute(value_ch);   
				
				char* index = new char[128];
				char* value = new char[128];

				sprintf ( index, "%u", j );
				sprintf ( value, "%f", gsl_matrix_get(coefficient_matrix, 1, j) );

				index_attribute->setValue( XMLString::transcode(index) );
				value_attribute->setValue( XMLString::transcode(value) );

				coefficient_element->setAttributeNode(index_attribute);
				coefficient_element->setAttributeNode(value_attribute);

                data_row->appendChild(coefficient_element);

				delete[] index;
				delete[] value;
			}

			gsl_matrix_free( coefficient_matrix );

		}//end outer for-loop		
	}
	catch( XMLException& e )
	{
		char* message = XMLString::transcode( e.getMessage() );
		cerr << "The following error occurred during the DOM creation: " << message << endl;
		XMLString::release( &message );

		#ifdef DEBUG_MODE
		cerr<<"ddas_write_results_to_file returning "<<SERIALIZATION_FAILURE<<"."<<endl;
		#endif

		return SERIALIZATION_FAILURE;
	}



	//serialize DOM document to local text file (LocalFileFormatTarget class)
	try
	{
		string resolved_name;
		int retval;

		//allocation
		DOMWriter* writer = ((DOMImplementationLS*)impl)->createDOMWriter();

		//resolve file name via BOINC's API
		retval = boinc_resolve_filename_s(RESULT_FILE, resolved_name);
		if (retval)
		{
			cerr<<"Couldn't resolve RESULT_FILE's name, \""<<RESULT_FILE<<"\"."<<endl;
		}

		XMLCh* file=XMLString::transcode( resolved_name.c_str() );
		LocalFileFormatTarget local_file(file);
		
		//set some writer output preferences
		if (writer->canSetFeature(XMLUni::fgDOMWRTDiscardDefaultContent, true))
			writer->setFeature(XMLUni::fgDOMWRTDiscardDefaultContent, true);
		if (writer->canSetFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true))
			writer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true);	
		
		//write root node and its children
		writer->writeNode(&local_file, *root);

		//free memory
		writer->release();
		XMLString::release(&file);
	}
	catch( XMLException& e )
	{
		char* message = XMLString::transcode( e.getMessage() );
		cerr << "XML toolkit initialization error: " << message << endl;
		XMLString::release( &message );
		
		#ifdef DEBUG_MODE
		cerr<<"ddas_write_results_to_file returning "<<SERIALIZATION_FAILURE<<"."<<endl;
		#endif

		return SERIALIZATION_FAILURE;
	}



	//required xerces teardown
	try
    {
		XMLPlatformUtils::Terminate();		
	}
    catch( xercesc::XMLException& e )
    {
		char* message = XMLString::transcode( e.getMessage() );
		cerr << "XML toolkit teardown error: " << message << endl;
		XMLString::release( &message );

		#ifdef DEBUG_MODE
		cerr<<"ddas_write_results_to_file returning "<<SERIALIZATION_FAILURE<<"."<<endl;
		#endif

		return SERIALIZATION_FAILURE;
    }	

	#ifdef DEBUG_MODE
	cerr<<"ddas_write_results_to_file returning "<<SERIALIZATION_SUCCESS<<"."<<endl;
	#endif

	return SERIALIZATION_SUCCESS;
}



/**
* @author Max Rupplin
* @date 5-15-08
* @param i A pointer to the iterator
*
* 'ddas_parse_state_file' parses the state file if one exists and sets the value of 'i'
*/
int ddas_parse_state_file( verylong* i )
{
	FILE* state_file;

	string resolved_name;

	int retval;

	//resolve real name
	retval = boinc_resolve_filename_s(STATE_FILE, resolved_name);
	if( retval )
	{
		cerr<<"Couldn't resolve state file's name, \""<<STATE_FILE<<"\"."<<endl;
		
		return 0;
	}

	//try and open file
	state_file = boinc_fopen( resolved_name.c_str(), "r" );
	if( !state_file )
	{
		cerr<<"Couldn't open state file's resolved_name using boinc_fopen, \""<<resolved_name<<"\"."<<endl;
        
		return 0;
	}

	//if file size is 0 (no state saved) just return
	if( get_file_size(state_file)==0 )
	{
		//set i = 1
		zone(i);

		return 0;
	}

	//else set starting_value, populate result_set and return
	init_vars_from_state_file( resolved_name, i );

	return 1;
}

/**
* @author Max Rupplin
* @date 5-15-08
*
* 'ddas_parse scoping file' parses the scoping file (logical name is 'scope') to initialize some important global variables.
*/
void ddas_parse_scoping_file()
{	
	#ifdef DEBUG_MODE
	cerr<<"ddas_parse_scoping_file called."<<endl;
	#endif

	FILE* scoping_file;
	string resolved_name;
	int retval;

	//resolve file name using BOINC's API
	retval = boinc_resolve_filename_s(SCOPING_FILE_NAME, resolved_name);
	if (retval)
	{
		cerr<<"Couldn't resolve scoping file's name, \""<<SCOPING_FILE_NAME<<"\"."<<endl;
		exit(-1);
	}

	//open file via BOINC's API
	scoping_file = boinc_fopen(resolved_name.c_str(), "r");
	if (!scoping_file) 
	{
		cerr<<"Couldn't open scoping file's resolved_name using boinc_fopen, \""<<resolved_name<<"\"."<<endl;
        exit(-1);
    }

	//set global values
	retval = init_vars_from_scoping_file( resolved_name, &starting_value, &ending_value, &results_to_return, &row_count, &independent_var_count, &dependent_var_count );
	if(!retval)
	{
		cerr<<"Error parsing the scoping file's data, \""<<resolved_name<<"\"."<<endl;
		exit(-1);
	}

	//perform some basic sanity checking
	verylong diff = 0;

	//how many results will actually be calculated
	zsub( ending_value, starting_value, &diff );

	//if the number of results to be calculated is less than the requested number to be returned fix it
	if( zscompare( diff, results_to_return) == -1 )
	{
		results_to_return = ztoint( diff );
		results_to_return++;
	}

	//free memory
	zfree(&diff);
	
	//set total_result_count 
	zsub( ending_value, starting_value, &total_result_count );
	zsadd( total_result_count, 1l, &total_result_count );

	//create result_set of appropriate size
	result_set = ddas_client_result_set_alloc( results_to_return );
	
	//add an extra column to determine the y intercept
	independent_var_count++;

	//close file
	fclose(scoping_file);

	#ifdef DEBUG_MODE
	ddas_print_global_vars();
	cerr<<"ddas_parse_scoping_file returning.\n";
	#endif
}


/**
* @author Max Rupplin
* @date 5-15-08
* 
* 'ddas_parse_date_file' populates the 'master' matrix which is used to then initialize the 'independent'
* and 'dependent' matrices.
*/
void ddas_parse_data_file()
{
	#ifdef DEBUG_MODE
	cerr<<"ddas_parse_data_file called.\n";
	#endif

	FILE* data_file;
	string resolved_name;
	char char_buffer[2048];
	int retval;			

	//allocate some memory
	master=gsl_matrix_alloc(row_count, (dependent_var_count+independent_var_count));

	//resolve file name using BOINC's API
	retval = boinc_resolve_filename_s(DATA_FILE_NAME, resolved_name);
	if (retval)
	{
		cerr<<"Couldn't resolve data file's name, \""<<DATA_FILE_NAME<<"\"."<<endl;
		exit(-1);
	}

	//open mapped file
	data_file = boinc_fopen(resolved_name.c_str(),"r");
	if (!data_file) 
	{
		cerr<<"Couldn't find the data file , whose resolved name is \""<<resolved_name<<"\"."<<endl;
        exit(-1);
    }

	//populate the master matrix
	for(int r=0; r<row_count; r++)
	{
		fscanf(data_file,"%s",char_buffer);

		//set up the 0th column for the y intercept
		gsl_matrix_set( master, r, 0, 1.0 );

		//have to set up the next column for the tokenizer
		gsl_matrix_set( master, r, 1, atof(strtok(char_buffer,",")));

		for(int c=2; c<(dependent_var_count+independent_var_count); c++)
		{
			//finally we can loop 
			gsl_matrix_set(master, r, c, atof(strtok(NULL,",")));
		}
	}

	#ifdef DEBUG_MODE
	cerr<<endl<<"gsl_matrix 'master' looks like:"<<endl;
	ddas_print_gsl_matrix(master);
	cerr<<"ddas_parse_data_file returning.\n";
	#endif
}


/**
* @author Max Rupplin
* @date 5-15-08
* @param resolved_name The actual name (not logical) of the file to open.
* @param i A pointer to the current iteration
*
* 'init_vars_from_state_file' checks for state_file and initializes certain global variables based upon it if found.
*/
int init_vars_from_state_file( string resolved_name, verylong* i )
{
	//initialize xerces
    try
    {
		XMLPlatformUtils::Initialize(); 
	}
	catch( XMLException& e )
	{
		char* message = XMLString::transcode( e.getMessage() );
		cerr << "XML toolkit initialization error: " << message << endl;
		XMLString::release( &message );
	}
	
	//open, parse state file
	try
	{
		DOMAttr*                bin_rep_attr;
        DOMAttr*                sse_attr;
        DOMAttr*                def_num_attr;
        DOMDocument*            doc;
        DOMNodeList*            data_rows;
        DOMElement*             current;
		DOMElement*				root;

		XercesDOMParser*        parser;

		XMLCh* iteration_ch		= XMLString::transcode("iteration");
		XMLCh* data_row_xmlch   = XMLString::transcode("data_row");
		XMLCh* bin_rep_xmlch    = XMLString::transcode("binary");
		XMLCh* sse_xmlch        = XMLString::transcode("SSE");
		XMLCh* def_num_xmlch    = XMLString::transcode("definition_number");
		XMLCh* coefficient_xmlch= XMLString::transcode("regression_coefficient");
		XMLCh* coeff_index_xmlch= XMLString::transcode("id");
		XMLCh* coeff_value_xmlch= XMLString::transcode("value");

		parser = new XercesDOMParser();
		parser->setValidationScheme(XercesDOMParser::Val_Always);
		parser->setDoNamespaces(false);
		parser->setDoSchema(false);
		parser->setLoadExternalDTD(false);
		parser->parse(resolved_name.c_str());

		doc             = parser->getDocument();
		data_rows       = doc->getElementsByTagName(data_row_xmlch);

		//set starting_value's value
		root = doc->getDocumentElement();
		const XMLCh* iteration_val = root->getAttributeNode( iteration_ch )->getValue();
		char* tmp = XMLString::transcode( iteration_val );

		//store in 'i'
		zsread( tmp, i );

		//size = number of data_row elements
		result_set->size    = (unsigned int)data_rows->getLength();

		//alloc some memory for the individual DDAS_CLIENT_RESULTs
		result_set->result  = new DDAS_CLIENT_RESULT[result_set->size];

		//for each DDAS_CLIENT_RESULT
		for( int i=0; i<result_set->size; i++)
		{
			//set current data_row
			current = (DOMElement*)(data_rows->item(i));

			//get current's attribute nodes
			bin_rep_attr = current->getAttributeNode( bin_rep_xmlch );
			sse_attr     = current->getAttributeNode( sse_xmlch );
			def_num_attr = current->getAttributeNode( def_num_xmlch );

			//convert attribute values from XMLCh* to char*
			char* sse_ch     = XMLString::transcode( sse_attr->getValue() );
			char* def_num_ch = XMLString::transcode( def_num_attr->getValue() );

			//store data in DDAS_CLIENT_RESULT_DATA struct
			DDAS_CLIENT_RESULT* current_result = &(result_set->result[i]);

			//store the sse
			current_result->sse = atof( sse_ch );

			//alloc some memory for the coefficients (gsl_vector)
			int num_coeffs = current->getElementsByTagName(coefficient_xmlch)->getLength();
			current_result->regression_coefficients = gsl_vector_alloc( num_coeffs );

			//copy definition number from char* to verylong
			current_result->definition_number = 0;
			zsread( def_num_ch, &(current_result->definition_number) );

			//for each coefficient
			for( int j=0; j<num_coeffs; j++ )
			{
				DOMElement* current_coeff = (DOMElement*)current->getElementsByTagName(coefficient_xmlch)->item(j);

                //store the value of the coefficient
				DOMAttr* attr = current_coeff->getAttributeNode(coeff_value_xmlch);

				const XMLCh* val = attr->getValue();

				char* value_ch = XMLString::transcode( val );

                double value = atof( value_ch );

				gsl_vector_set( current_result->regression_coefficients, j, value);
			}
		}

	}
	catch( XMLException& e )
	{
		char* message = XMLString::transcode( e.getMessage() );
		cerr << "XML toolkit initialization error: " << message << endl;
		XMLString::release( &message );

		#ifdef DEBUG_MODE
		cerr<<"init_vars_from_state_file returning 0."<<endl;
		#endif

		return 0;
	}

	//requisite xerces teardown
	try
    {
		XMLPlatformUtils::Terminate();

		#ifdef DEBUG_MODE
		cerr<<"init_vars_from_state_file returning 1."<<endl;
		#endif

		return 1;
	}
    catch( xercesc::XMLException& e )
    {
		char* message = XMLString::transcode( e.getMessage() );
		cerr << "XML toolkit teardown error: " << message << endl;
		XMLString::release( &message );

		#ifdef DEBUG_MODE
		cerr<<"init_vars_from_state_file returning 0."<<endl;
		#endif

		return 0;
    }
}


/**
* @author Max Rupplin
* @date 5-15-08
* @param resolved_name The actual name (not logical) of the scoping file.
* @param start A pointer to the starting iteration 
* @param end A pointer to the ending iteration 
* @param numberResults The number of results to return 
* @param numberRows The number of rows in the data set
* @param numberX The number of independent variables
* @param numberY The number of dependent variables 
*
* 'init_vars_from_scoping_file' checks for scoping_file and initializes certain global variables based upon it if found
*/
int init_vars_from_scoping_file(string resolved_name, verylong* start , verylong* end, int* numberResults, int* numberRows, int* numberX, int* numberY)
{
	#ifdef DEBUG_MODE
	cerr<<"init_scoping_variables called."<<endl;
	#endif

	//initialize xerces
    try
    {
		XMLPlatformUtils::Initialize(); 
	}
	catch( XMLException& e )
	{
		char* message = XMLString::transcode( e.getMessage() );
		cerr << "XML toolkit initialization error: " << message << endl;
		XMLString::release( &message );
	}

	//open, parse scoping file
	try
	{
		XercesDOMParser xdp;
		XercesDOMParser* parser = &xdp;

		parser->setValidationScheme(XercesDOMParser::Val_Always);
		parser->setDoNamespaces(false);
		parser->setDoSchema(false);
		parser->setLoadExternalDTD(false);
		parser->parse(resolved_name.c_str());

		DOMDocument* doc = parser->getDocument();
		DOMElement* root = doc->getDocumentElement();

		XMLCh* start_xmlch		= XMLString::transcode("start");
		XMLCh* end_xmlch		= XMLString::transcode("end");
		XMLCh* numResults_xmlch = XMLString::transcode("numberResults");
		XMLCh* numRows_xmlch    = XMLString::transcode("numberRows");
		XMLCh* numX_xmlch       = XMLString::transcode("numberX");
		XMLCh* numY_xmlch		= XMLString::transcode("numberY");
		XMLCh* jobID_xmlch		= XMLString::transcode("jobID");

		char* startC		= XMLString::transcode( (root->getAttributeNode(start_xmlch)->getValue()) ); 
		char* endC			= XMLString::transcode( (root->getAttributeNode(end_xmlch)->getValue()) ); 
		char* numResultsC	= XMLString::transcode( (root->getAttributeNode(numResults_xmlch)->getValue()) );
		char* numRowsC		= XMLString::transcode( (root->getAttributeNode(numRows_xmlch)->getValue()) );
		char* numXC			= XMLString::transcode( (root->getAttributeNode(numX_xmlch)->getValue()) );
		char* numYC			= XMLString::transcode( (root->getAttributeNode(numY_xmlch)->getValue()) );
		
		#ifdef DEBUG_MODE
		cerr<<"startC: "		<<startC<<endl;
		cerr<<"endC: "			<<endC<<endl;
		cerr<<"numResultsC: "	<<numResultsC<<endl;
		cerr<<"numRowsC: "		<<numRowsC<<endl;
		cerr<<"numXC: "			<<numXC<<endl;
		cerr<<"numYC: "			<<numYC<<endl;
		#endif

		zsread(startC, start);
		zsread(endC, end);
		*numberResults	= atoi(numResultsC);
		*numberRows		= atoi(numRowsC);
		*numberX		= atoi(numXC);
		*numberY		= atoi(numYC);

		delete[] startC;
		delete[] endC;
		delete[] numResultsC;
		delete[] numRowsC;
		delete[] numXC;
		delete[] numYC;
	}
	catch( XMLException& e )
	{
		char* message = XMLString::transcode( e.getMessage() );
		cerr << "XML toolkit initialization error: " << message << endl;
		XMLString::release( &message );

		#ifdef DEBUG_MODE
		cerr<<"init_scoping_variables returning 0."<<endl;
		#endif

		return 0;
	}

	//requisite xerces teardown
	try
    {
		XMLPlatformUtils::Terminate();

		#ifdef DEBUG_MODE
		cerr<<"init_scoping_variables returning 1."<<endl;
		#endif

		return 1;
	}
    catch( xercesc::XMLException& e )
    {
		char* message = XMLString::transcode( e.getMessage() );
		cerr << "XML toolkit teardown error: " << message << endl;
		XMLString::release( &message );

		#ifdef DEBUG_MODE
		cerr<<"init_scoping_variables returning 0."<<endl;
		#endif

		return 0;
    }
}